/* TYPE and LIMITS used by Sheets
(header <limits> should be included) */
typedef unsigned short ROW_NUM;	//0~65535
typedef unsigned char COL_NUM;	//0~255

#define ROW_MAX USHRT_MAX		//65535
#define COL_MAX UCHAR_MAX		//255

#define CELL_CONTENT_MAX	1024

/* Define the structure for Cell Position*/
typedef struct
{
	ROW_NUM iRow;
	COL_NUM iCol;
} CELLPOS;

#define CELL_DEFHEIGHT	18
#define CELL_DEFWIDTH	72
#define CELL_DEFBKCLR	RGB(255,255,255)
#define CELL_DEFTXCLR	RGB(0,0,0)
#define CELL_DEFHALIGN	DT_LEFT
#define CELL_DEFVALIGN	DT_TOP

#define CELL_DEF_FONT_NAME			TEXT("Times New Roman")
#define CELL_DEF_FONT_ATTR			 0

#define CELL_FONT_ATTR_BOLD          1
#define CELL_FONT_ATTR_ITALIC        2
#define CELL_FONT_ATTR_UNDERLINE     4
#define CELL_FONT_ATTR_STRIKEOUT     8

/* Define the style of cells */
//typedef BYTE CellPosition;	//8 bits
//#define CELL_SINGLE		0
//#define CELL_TOP		0x01
//#define CELL_BOTTOM		0x02
//#define CELL_LEFT		0x03
//#define CELL_RIGHT		0x04
//#define CELL_CENTER		0x05

/****************************************
* Define the class for Cells
***/
class CellNode
{
public:
	// pointers that point to the surrounding cells clockwise:
	//Cell* pCellAbove;		// point to the cell above
	CellNode* pCellRight;		// point to the cell on the right
	CellNode* pCellBelow;		// point to the cell below
	//Cell* pCellLeft;		// point to the cell on the left

	CellNode(CellNode* pcRight = 0, CellNode* pCellBelow =0)
		:pCellRight(pcRight), pCellBelow(pCellBelow)
	{}
};

class RowHeader : public CellNode
{
public:
	ROW_NUM iRowNum;	// Row Number
	int iRowHeight;		// Height, for rows only
	RowHeader* pRowAbove;
	RowHeader() {iRowNum = 0; iRowHeight = CELL_DEFHEIGHT;
	iCount = 0; pRowAbove = 0;}
	void CountIncrease(){iCount++;}
	void CountDecrease(){iCount--;}
	bool Empty(){return iCount ==0;}
	const int GetCount(){return iCount;}
protected:
	int iCount;			// Count of all Cells in this row
};

class ColHeader : public CellNode
{
public:
	COL_NUM iColNum;	// Column Number
	int iColWidth;		// Width, for columns only
	ColHeader* pColLeft;
	ColHeader() {iColNum = 0; iColWidth = CELL_DEFWIDTH; 
	iCount = 0; pColLeft =0;}
	void CountIncrease(){iCount++;}
	void CountDecrease(){iCount--;}
	bool Empty(){return iCount ==0;}
	const int GetCount(){return iCount;}
protected:
	int iCount;			// Count of all Cells in this column
};

class Cell : public CellNode
{
	friend class Sheet;
public:
	bool IsDefaultStyle()const
		{return backColor==CELL_DEFBKCLR && textColor == CELL_DEFTXCLR
				&& textHAlign == CELL_DEFHALIGN && textVAlign == CELL_DEFVALIGN
				&& fontAttr == CELL_DEF_FONT_ATTR && fontName == CELL_DEF_FONT_NAME;}
	MemState GetState(ModifiedField mf = CELL_MF_CONTENT)
	{
		MemState state;
		if((mf & CELL_MF_CONTENT) != 0)
			state.Content = strContent;
		state.bkColor = backColor;
		state.txColor = textColor;
		state.textHAlign = textHAlign;
		state.textVAlign = textVAlign;
		state.fontAttr = fontAttr;
		state.fontName = fontName;
		return state;
	}

	void SetState(MemState& state, ModifiedField mf = CELL_MF_CONTENT)
	{
		if ((mf & CELL_MF_CONTENT) != 0)
			strContent = state.Content;
		if ((mf & CELL_MF_TXCOLOR) != 0)
			textColor = state.txColor;
		if ((mf & CELL_MF_BKCOLOR) != 0)
			backColor = state.bkColor;
		if ((mf & CELL_MF_HALIGN) != 0)
			textHAlign = state.textHAlign;
		if ((mf & CELL_MF_VALIGN) != 0)
			textVAlign = state.textVAlign;
		if ((mf & CELL_MF_FONTATTR) != 0)
			fontAttr = state.fontAttr;
		if ((mf & CELL_MF_FONT) != 0)
			fontName = state.fontName;
	}
	wstring* GetContent(){return &strContent;}
	COLORREF GetBackColor(){return backColor;}
	COLORREF GetTextColor(){return textColor;}
	void SetTextColor(COLORREF& col){textColor = col;}
	void SetBackColor(COLORREF& col){backColor = col;}
	UINT GetTextHAlign(){return textHAlign;}
	UINT GetTextVAlign(){return textVAlign;}
	UINT GetFontAttr(){return fontAttr;}
	wstring* GetFontName(){return &fontName;}
	void SetTextHAlign(UINT& aln){textHAlign = aln;}
	void SetTextVAlign(UINT& aln){textVAlign = aln;}
	void SetFontAttr(UINT& attr){fontAttr = attr;}
	void SetFontName(const wstring& font){fontName = font;}
	COL_NUM GetColumnNumber(){return pcColHeader->iColNum;}
	ROW_NUM GetRowNumber(){return pcRowHeader->iRowNum;}
protected:
	wstring strContent;		// the content of the cell
	RowHeader* pcRowHeader;
	ColHeader* pcColHeader;
	COLORREF backColor;
	COLORREF textColor;
	UINT	textHAlign;
	UINT	textVAlign;
	UINT	fontAttr;
	wstring fontName;

	Cell(RowHeader* pRowH, ColHeader* pColH, CellNode* pcBelow, CellNode* pcRight)
		:strContent(TEXT("")),
		pcRowHeader(pRowH),
		pcColHeader(pColH),
		CellNode(pcRight, pcBelow)
	{backColor = CELL_DEFBKCLR; textColor = CELL_DEFTXCLR;
	 textHAlign = CELL_DEFHALIGN; textVAlign = CELL_DEFVALIGN; 
	 fontAttr = CELL_DEF_FONT_ATTR; fontName = CELL_DEF_FONT_NAME;}
};
